import os
from django.shortcuts import render
from django.http import HttpResponseRedirect,HttpResponse
# Create your views here.
from app01 import models
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.urls import reverse
#导入forms组件
from app01.myforms import MyRegForm
from django.http import JsonResponse
from django.urls import reverse

#注册
def register(request):
    form_obj=MyRegForm()
    #状态码core,报错信息msg,core=2000代表用户输入格式错误
    back_dict = {'core':1000,'msg':''}
    if request.method=='POST':
        #校验数据是否合法
        form_obj=MyRegForm(request.POST)
        #所有字段都满足校验条件,才为true
        if form_obj.is_valid():
            #cleaned_data 满足校验条件的字段,{key:value}
            clean_list = form_obj.cleaned_data#['','','','']
            clean_data={}
            #如何获取ajax请求的数据
            for key in clean_list:
                clean_data[key]=request.POST.get(key)
            # print(clean_data,33)
            #将字典中的confirm_password键值对删除,使用**打散,直接创建用户
            clean_data.pop('confirm_password')
            #获取到用户头像,针对用户头像一定要判断用户是否上传了头像.
            file_obj = request.FILES.get('avatar')
            if file_obj:
                #这个键是UserInfo中avater字段
                clean_data['avatar']=file_obj
            #给UserInfo创建普通用户
            ''' 判断用户是否注册已经在forms组件中实现了 '''
            models.UserInfo.objects.create_user(**clean_data)
            #这是ajax请求,所有的返回会被回调函数success获取到,没办法直接重定向
            #将要重定向的url发送给ajax
            back_dict['url']='/app01/login/'
            return JsonResponse(back_dict)
        else:
            back_dict['core']=2000
            back_dict['msg']=form_obj.errors
            # print(back_dict,2000)
        return JsonResponse(back_dict,json_dumps_params={'ensure_ascii':False})
    return render(request,'app01/register.html',locals())
#登录
def login(request):
    url = request.GET.get('url',False)
    # print(url,9090)
    if request.method=='POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        code = request.POST.get('code')
        #产生的随机验证码保存在session中
        random_code = request.session.get('code')
        #校验用户是否在表中，且密码是否正确
        user_obj = auth.authenticate(request,username=username,password=password)
        #创建一个字典，将数据传输过去
        result = {'code':1000,'msg':'','url':''}
        if code.upper()==random_code.upper():#验证码不区分大小写
            # print(code,random_code,68)
            #验证码正确
            if user_obj:
                #用户和密码正确
                #保存session
                auth.login(request,user_obj)
                # print('用户密码正确')
                #用户登录成功就会创建一个站点
                blog=models.Blog.objects.filter(site_name=username).first()
                if not blog:#用户如果没有创建自己的blog，就帮用户创建
                    user_blog=models.Blog.objects.create(site_name=username,site_theme=str(username)+'.css')
                    #因为用户的个人站点在用户表中，需要关联上
                    models.UserInfo.objects.filter(username=username).update(blog=user_blog)
                #代表用户登录成功,code=1000登录成功
                #登录成功跳转的地方，直接在登录页面进行登录的，根据用户类型去不同url
                if username[:5]=='admin':
                    #如果是管理员登录，跳转到管理员的管理界面
                    result['url']='/app01/admin/'
                elif username[:5]=='51200':
                    result['url'] = '/app01/backend/'
                else:
                    result['url']='/app01/backend/'
                #如果是从特定的位置进行登录，登录成功返回该位置。
                if url:
                    result['url']=url
                result['msg']='登录成功'
            else:
                #代表密码错误
                result['code']=2000
                result['msg']='用户或密码错误'
        else:
            result['code']=3000
            result['msg']='验证码错误'
        # print(result,'发送数据给ajax的回调函数前字典数据')
        return JsonResponse(result)


    return render(request,'app01/login.html')

import random
def get_random(request):
    return random.randint(0,255),random.randint(0,255),random.randint(0,255)

from io import BytesIO,StringIO
'''
内存管理器模块
BytesIO：临时帮你存储数据，返回的数据是二进制
StringIO：临时帮你存储数据，返回的数据是str
'''
from PIL import Image,ImageDraw,ImageFont
'''
图片相关的模块
pip3 install pillow

'''
'''
Image 生成图片
ImageDraw: 在图片上乱涂乱画
ImageFont: 控制字体样式

'''
#生成随机验证码图片，用户登录的时使用
def get_code(request):
    tup=get_random(request)
    #推到步骤1，不使用了
    # with open(r'static\img\55.jpg','rb')as fp:
    #     img=fp.read()
    # return HttpResponse(img)
    #推导模式2
    # img_obj=Image.new('RGB',(280,30),"green")
    #可以放三基色，0-255
    # img_obj = Image.new('RGB', (280, 30), tup)
    # #先将图片对象保存起来，再将图片对象读取出来
    # with open('xxx.png','wb') as fp:
    #     img_obj.save(fp,'png')
    # with open('xxx.png','rb')as fp:
    #     data=fp.read()
    # return HttpResponse(data)
    '''推导步骤3，文件存储繁琐，IO操作效率低。借助内存管理器模块'''
    # img_obj = Image.new('RGB', (280, 30), tup)
    # io_obj = BytesIO()#生成内存管理器对象，可以看作文件句柄
    # img_obj.save(io_obj,'png')
    # return HttpResponse(io_obj.getvalue()) #从内存管理器中读取二进制的图片数据返回给前端

    '''最终步骤，写图片验证码'''
    img_obj = Image.new('RGB', (280, 30), tup)
    img_draw = ImageDraw.Draw(img_obj)  #产生画笔对象
    img_font = ImageFont.truetype(r'static\font\111.ttf',28) #字体样式，大小
    #随机验证码 5位数的随机验证码，0-9，a-z，A-Z
    code = ''
    for i in range(5):
        random_upper = chr(random.randint(65,90))
        random_lower = chr(random.randint(97,122))
        random_int =str(random.randint(0,9))
        tmp = random.choice([random_upper,random_lower,random_int])
        #将产生的随机字符串写入到图片上。
        '''
        为什么一个一个的写，而不是生成好再写。
        1、一个个写，能够控制每个字之间的空隙
        '''
        img_draw.text(((i+1)*40,-2),tmp,get_random(request),img_font)
        #画笔      写字      位置      内容        颜色          字体样式
        code+=tmp#拿到返回给随机字符串
        #随机验证码在登录的视图里面需要用到，要比对，要找到地方存起来，其他视图函数也可以使用的。
        #用session存起来
    request.session['code']=code
    io_obj = BytesIO()
    img_obj.save(io_obj,'png')
    #拿到存到IO里面的字符串，将随机验证码返回
    return HttpResponse(io_obj.getvalue())
#导入自定义的分页器
from Utils import paginator
#主页面
def home(request):
    page_num = request.GET.get('page',1)
    #只有没有删除的文章吹显示出来
    all_msg = models.Article.objects.filter(is_active=1)
    all_count = all_msg.count()
    url = request.path_info
    c_page=all_msg
    page_html=''
    if all_count>5:
        page_obj = paginator.Pagination(base_url=url,current_page=page_num,total_count=all_count,per_page_count=5,max_pager_num=5)
        # 拿到当前页的所有数据,在前端循环c_page, 展示当前页的所有内容
        c_page = all_msg[page_obj.start:page_obj.end]
        # print(c_page,211)
        #获取到分页器的html代码
        page_html=page_obj.page_html()
    #拿到用户的头像的url
    url_dic = {} #
    for obj in c_page:
        lis =  models.Article.objects.filter(pk=obj.pk).values('blog__userinfo__avatar','blog__userinfo__username')
        url=lis[0]['blog__userinfo__avatar']
        username = lis[0]['blog__userinfo__username']
        url_dic[obj]=[url,username]
    dic={'c_page':c_page,'page_html':page_html,'url_dic':url_dic,'home_url':request.get_full_path(),'request':request}

    #文件和文章推荐，
    good_article = models.Article.objects.all().order_by('-comment_num')[0:5]
    good_file = models.UserFile.objects.all().order_by('-number')[0:5]
    # #优秀用户
    # good_user =models.Article.objects.values('blog').annotate(article_num=Count('blog')).order_by('-article_num')[:5]
    #最新文章
    new_article = models.Article.objects.order_by('-create_time')[:5]
    #最新文件
    new_files = models.UserFile.objects.order_by('-create_time')[:5]
    return render(request,'app01/home.html',locals())

#文件资源主页显示
@login_required
def file_home(request):
    #将没有标志为删除与可以共享的文件展示出来
    all_file = models.UserFile.objects.filter(is_active=1,share=True)
    #当前页所有数据
    c_page=all_file
    page_html = ''
    cur_url=request.get_full_path()
    if all_file.count()>5:
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page, total_count=all_file.count(), per_page_count=5, max_pager_num=5)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = all_file[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
        # 文件和文章推荐，
        good_article = models.Article.objects.all().order_by('-comment_num')[0:5]
        good_file = models.UserFile.objects.all().order_by('-number')[0:5]
        # #优秀用户
        # good_user =models.Article.objects.values('blog').annotate(article_num=Count('blog')).order_by('-article_num')[:5]
        # 最新文章
        new_article = models.Article.objects.order_by('-create_time')[:5]
        # 最新文件
        new_files = models.UserFile.objects.order_by('-create_time')[:5]
    return render(request,'app01/home_file.html',locals())



#退出登录
@login_required
def logout(request):
    # url = request.GET.get('url', False)
    auth.logout(request)
    return HttpResponseRedirect(reverse('app01_home'))
#修改密码
@login_required
def set_password(request):
    if request.is_ajax():
        if request.method=='POST':
            old_pwd=request.POST.get('old_pwd')
            new_pwd=request.POST.get('new_pwd')
            confirm_pwd=request.POST.get('confirm_pwd')
            is_right = request.user.check_password(old_pwd)
            print(new_pwd,confirm_pwd,'241241')
            dic={'code':1000,'msg':''}
            if is_right:#说明旧密码没有错误。
                if new_pwd==confirm_pwd:#说明输入的两次新密码一致
                    #修改密码
                    request.user.set_password(new_pwd)
                    #保存结果到数据库中
                    request.user.save()
                    # 跳转到登录界面重新登录
                    dic['msg'] = '修改成功'
                    #注销当前登录的用户
                    logout(request)
                else:
                    dic['msg']='两次密码不一致'
                    dic['code']=2000
            else:
                dic['code']=3000
                dic['msg']='原密码有误'
            # print(dic,197197)
            return JsonResponse(dic)
from django.db.models import Count, QuerySet
from django.db.models.functions import TruncMonth #按时间月进行分组
#个人站点视图函数，每个人的站点是 http://127.0.0.1:8000/site/用户名【拼音】
def site(request,username,**kwargs):#有其他路由指向这里，我们使用**kwargs来接收
    """
    :param request:
    :param username:
    :param kwargs:如果该参数有值，则需要对article_obj进行进一步的筛选，展示的数据变化，其他格式都一样
    :return:
    """
    #将转换器的名称作为形式参数
    #先校验当前用户名对应的站点是否存在，如果不存在就跳转到固定的页面提示用户
    back_url=request.GET.get('url',reverse('app01_home'))
    user_obj = models.UserInfo.objects.filter(username=username).first()
    if user_obj:#
        #站点存在的话，就将该站点的所有资源展示出来
        blog = user_obj.blog#子查询，正向查询用外键字段
        try:
            article_obj = models.Resource.objects.filter(uploader=user_obj,is_delete=False)#侧边栏功能就是对这个queryset对象进一步的筛选而来，queryset对象可以再点filter进行过滤
            #如果is_web=1则说明展示的内容是资源
            is_web = 1

        except:
            return render(request, 'app01/error.html')
        '''如果**kwargs有值，说明用户点击了侧边栏的筛选，我们需要对article_obj做进一步的筛选'''
        if kwargs:
            if 'tag_id' in kwargs:
                article_obj = models.Article.objects.filter(tags=kwargs.get('tag_id'),is_active=True)
                is_web = 0
            elif 'category_id' in kwargs:
                article_obj = models.Article.objects.filter(category=kwargs.get('category_id'),is_active=True)
                is_web = 0
            elif 'archive_month' in kwargs:
                year,month = kwargs.get('archive_month').split('-')
                article_obj=models.Article.objects.filter(blog=blog,create_time__year=year,create_time__month=month,is_active=True)
                is_web = 0
            elif 'web_source_id' in kwargs:
                #拿到对应的分类，找到有多少资源属于该分类
                article_obj = models.Resource.objects.filter(categoryid_id=kwargs.get('web_source_id'),is_delete=False)
                #说明这是要显示web资源库的内容
                is_web=1
                print(article_obj.count(),314)
            #点击查看web资源库的东西
        #分页功能
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj #条数小于6时，展示所有的数据
        page_html = ''
        if article_obj.count() >= 6:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                            total_count=article_obj.count(), per_page_count=5, max_pager_num=5)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据

        return render(request,'app01/site.html',locals())

    else:
        #说明没有该用户的站点，返回一个404页面，是一个正常的页面
        return render(request,'app01/error.html')

#文章详情视图
def article_detail(request,article_id,username):
    #先写正确的逻辑，后面再补全。
    blog = models.Blog.objects.filter(userinfo__username=username).first()
    #获取到文章对象
    user_obj=models.UserInfo.objects.filter(username=username)
    #还要限制是哪个用户的哪篇文章
    article_obj = models.Article.objects.filter(pk=article_id,blog__userinfo__username=username,is_active=1).first()
    # 应该先判断用户名存在、或文章id是否存在。只要由一个不符合，就报错。
    #文章的点赞数和点踩传递过去
    click = models.Article.objects.filter(pk=article_id).first()
    if not user_obj or not article_obj:
        return render(request, 'app01/error.html')
    url = request.get_full_path()
    back_url=request.GET.get('url','/app01/home/')
    '''将文章的评论展示出来'''
    article_comment = models.Comment.objects.filter(article=article_id)
    '''对评论进行分页操作'''
    # 拿到当前的页码数
    c_page=article_comment#显示的所有评论
    '''查看该文章用户是否收藏了'''
    collage=False
    try:
        collage= models.User2Article.objects.filter(article_id=article_id,user=request.user).first()
    except:
        pass
    #用户可能没有登录
    img='/static/img/noactive.png/'
    col_img='no'#代表用户未收藏该文章
    if collage:
        img = '/static/img/active.png/'
        col_img='yes' #代表用户已经收藏该文章了

    return render(request,'app01/article_detail.html',locals())

@login_required
def cellact_article(request):
    if request.is_ajax():
        if request.method=='POST':
            dic = {'code':1000,'col_img':''}
            operate=request.POST.get('operate')
            operate = json.loads(operate)
            article_id = request.POST.get('article_id')
            obj=models.User2Article.objects.filter(article_id=article_id,user=request.user).filter()
            if obj: #有收藏该文章
                if not operate:#收藏了，且用户要取消收藏了。才删除记录
                    #把收藏记录删除掉
                    obj.delete()
                    dic['col_img']='no'#取消收藏了
                    return JsonResponse(dic)
            else:#代表用户没有收藏该文章
                if operate:#代表用户要收藏该文章
                    dic['col_img']='yes'#收藏了
                    models.User2Article.objects.create(article_id=article_id, user=request.user)
                    return JsonResponse(dic)


import json
from django.db.models import F
from django.db import transaction#导入事务，
#点踩点赞功能的函数
def up_or_down(request):
    if request.is_ajax():
        dic={'coed':1000,'msg':'请先登录。'}
        # 判断当前用户是否登录
        if request.method=='POST':
            if request.user.is_authenticated:
                is_Up = request.POST.get('is_Up') #is_Up 是json格式的'true', loads 是json转python
                article_id =request.POST.get('article_id')
                is_Up= json.loads(is_Up)
                #2、判断当前文章是否是当前用户写的。
                username = request.user.username
                #找到当前用户写的文章，看文章的id是否是当前文章
                article_obj = models.UserInfo.objects.filter(blog__article=article_id,username=username)
                user_obj = models.UserInfo.objects.filter(username=username).first()
                if not article_obj:#文章不是当前用户写的。
                    #校验用户是否点过赞了。
                    #到点赞点踩表中查看，该用户的id是否有该文章id的点赞点踩记录
                    upp_obj = models.UpAndDown.objects.filter(user=user_obj.id,article=article_id)
                    if not upp_obj:
                        # 在用户为点赞点踩时，就可以进行点，并且记录到数据库中。
                        # 同步到点赞点踩表的时候，不要忘记了同步到文章表中中点赞点踩中,is_Up已经转成了bool类型刚好对应
                        # 1、在点赞点踩表中记录
                        models.UpAndDown.objects.create(user_id=user_obj.id, article_id=article_id, is_up=is_Up)
                        # 2、在文章表中，给点赞或点踩加1，使用F对象
                        if is_Up:  # 点赞数加1
                            models.Article.objects.filter(id=article_id).update(up_num=F('up_num') + 1)
                            dic['code'] = 1000
                            msg = '点赞成功'
                            print(msg)
                        else:  # 点踩数加1
                            models.Article.objects.filter(id=article_id).update(down_num=F('down_num') + 1)
                            dic['code'] = 1000
                            msg = '点踩成功'
                            print(msg)
                    else:
                        msg = '不能重复点赞或点踩'#通了
                        dic['code'] = 2000
                        print(msg)

                else:
                    msg ='不能推荐自己写的文章'#通了
                    dic['code']=3000
                    print(msg)

            else:
                msg=f'<a href="/app01/login/" id="id_login">请先登录。</a>'
                dic['code']=4000
            dic['msg']=msg
        return JsonResponse(dic)
#文章评论功能
@login_required
def comment(request):
    #自己也可以给自己的文章进行评论
    if request.is_ajax():
        if request.method=='POST':
            dic={'code':1000,'msg':''}
            #用户有一个禁言的字段，limit =True就是禁止学生发表评论
            limit = models.UserInfo.objects.filter(username=request.user.username,limit=0)
            if limit:
                if request.user.is_authenticated:
                    article_id = request.POST.get('article_id')
                    content = request.POST.get('content')
                    parent_id=request.POST.get('parent_id')
                    #直接操作评论表，存储数据，两张表，
                    with transaction.atomic():#在一个with之下都是一个事务
                        #给文章的评论数加1
                        models.Article.objects.filter(pk=article_id).update(comment_num=F('comment_num')+1)
                        #将哪个用户对哪篇文章进行了评论，写到数据库的评论表中。
                        models.Comment.objects.create(user=request.user,article_id=article_id,content=content,parent_id=parent_id)
                        dic['msg']='评论成功'
                else:
                    dic['msg']='用户未登录'
                    dic['code']=2000
            else:
                #用户已经被禁言，无法发表评论
                dic['code']=403
                dic['msg']='您已经被禁言，无法发布评论。'
            return JsonResponse(dic)
from Utils import paginator1
@login_required
def backend(request):
    '''
        文章页显示
    '''
    #拿到登录的用户所有的文章，显示出来
    article_obj = models.Article.objects.filter(blog__userinfo=request.user,is_active=1)
    c_page=article_obj
    #文章的分页
    page_html=''
    if article_obj.count()>=8:
        cur_page = request.GET.get('page',1)
        pagenate = paginator.Pagination(base_url=request.path_info,current_page=cur_page,total_count=article_obj.count(),per_page_count=8,max_pager_num=8)
        page_html=pagenate.page_html()
        c_page = article_obj[pagenate.start:pagenate.end]
    '用户文件资源显示'
    #根据外键字段userinfo,一种传递对象,一种给真实外键userinfo_id 传递键值.
    user_file = models.UserFile.objects.filter(userinfo=request.user,is_active=1)
    file_page_html=''#没有文件的时候，就不要分页器
    if user_file.count() >= 3:
        user_page = request.GET.get('page', 1)
        # 文件的分页
        file_pagenate = paginator.Pagination(base_url=request.path_info, current_page=user_page, total_count=user_file.count(), per_page_count=3, max_pager_num=4)
        file_page_html = file_pagenate.page_html()
        user_file = user_file[file_pagenate.start:file_pagenate.end]
    #当前用户的文章标签
    tags = models.Tag.objects.filter(blog__userinfo=request.user)
    #当前用户的文章分类
    categorys = models.Category.objects.filter(blog__userinfo=request.user)
    #文件的删除功能
    if request.is_ajax():
        dic={'code':100,'msg':''}
        if request.method=='POST' and 'for_del_file' in request.POST:
            file_id = request.POST.get('file_id')
            op = request.POST.get('op') #前端的布尔值通过json.loads() 可以转成python的布尔值
            op = json.loads(op)
            if op:#op为true说明用户要删除文件,不是就不删除操作
                #通过is_active代表用户是否删除了文件.
                try:
                    obj=models.UserFile.objects.filter(id=file_id).update(is_active=0)
                    dic['code']=200
                    dic['msg']='文件删除成功'
                    return JsonResponse(dic)
                except :
                    dic['code']=500
                    dic['msg']='删除失败，请稍后再操作。'
                    return JsonResponse(dic)
        elif request.method=='GET' and 'for_del_article' in request.GET:
            #这个是删除文章的逻辑
            article_id = request.GET.get('article_id')
            op = request.GET.get('op')
            op = json.loads(op)
            if op:
                dic['code']=200
                dic['msg']='文章删除成功。'
                try:
                    models.Article.objects.filter(pk=article_id).update(is_active=0)
                    return JsonResponse(dic)
                except :
                    dic['code']=500
                    dic['msg']='删除失败，请稍后再操作。'
                    return JsonResponse(dic)
    #文章标签和分类增加
    if request.is_ajax():
        if 'fortag' in request.POST:
            dic={'msg':'增加标签成功','code':1000}
            addtag = request.POST.get('add_tag',None)
            print(addtag,502)
            if  addtag and addtag!='输入新增标签名':
                try:
                    blog = models.Blog.objects.filter(userinfo=request.user).first()#拿到个人站点对象
                    #增加标签
                    models.Tag.objects.create(name=addtag,blog=blog)
                except :
                    dic['msg']='增加失败，请稍后再继续'
            else:
                dic['msg']='请输入新标签的名字。'
                dic['code']=2000
            return JsonResponse(dic)
        elif 'forcategory' in request.POST:
            dic = {'msg': '增加新分类成功', 'code': 1000}
            addcategory = request.POST.get('add_category', None)
            if addcategory and addcategory != '输入新增分类名':
                try:
                    blog = models.Blog.objects.filter(userinfo=request.user).first()  # 拿到个人站点对象
                    # 增加标签
                    models.Category.objects.create(name=addcategory, blog=blog)
                except:
                    dic['msg'] = '增加失败，请稍后再继续'
            else:
                dic['msg'] = '请输入新分类的名字。'
                dic['code'] = 2000
            return JsonResponse(dic)


    return render(request,'app01/backend.html',locals())

from bs4 import BeautifulSoup
#添加文章
@login_required
def add_article(request):
    #获取到当前用户的分类和标签
    category_obj = models.Category.objects.filter(blog__userinfo=request.user)
    tag_obj = models.Tag.objects.filter(blog__userinfo=request.user)
    #用户文件的资源
    user_file = models.UserFile.objects.filter(userinfo=request.user,is_active=1)
    if request.method=='POST':
        if 'OP' in request.POST:
            op_obj= request.POST.get('OP')
            name =request.POST.get('name')
            name_str = request.POST.get('str')
            dic = {'msg': f'增加文章{name_str}成功', 'code': 100}
            if op_obj=='Category':
                table = models.Category
            else:
                table= models.Tag
            if name:
                obj = table.objects.filter(name=name,blog__userinfo=request.user)
                if not obj:
                    blog = models.Blog.objects.filter(userinfo=request.user).first()
                    table.objects.create(name=name, blog=blog)
                else:
                    dic['msg'] = f'该{name_str}名已经存在了。'
                    dic['code'] = 120
            else:
                dic['msg'] = f'不能创建空字符串的{name_str}。'
                dic['code'] = 404
            return JsonResponse(dic)
        title = request.POST.get('title',request.user.username+' article')
        content = request.POST.get('content')
        category_id = request.POST.get('category')
        tags_id_list = request.POST.getlist('tag')#多选使用getlist来拿数据
        #文章简介
        #选择要操作的内容，和解释器类型
        soup = BeautifulSoup(content,'html.parser')
       #拿到所有的数据
        tags = soup.find_all()
        for tag in tags:
            #tag.name拿到所有的标签名
            #删除script标签,防止xss攻击
            if tag.name=='script':
                tag.decompose()
        #获取到所有文本,只切取150个文本，不切取标签字符
        desc= soup.text[0:150]
        # content='<body class="ke-content">'+content+'</body>'
        blog =models.Blog.objects.filter(site_name=request.user.username).first()
        #给文章表添加文章
        article = models.Article.objects.create(title=title,desc=desc,blog=blog,category_id=category_id,content=content)
        #文章与标签多对多关系，我们使用的是半自动，没有办法使用add,set,remove，clear等方法
        #直接手动操作文章标签表，给文章添加多个标签。批量插入
        article_obj_list=[]
        for tag_id in tags_id_list:
           article_obj_list.append(models.Article2Tag(article=article,tag_id=tag_id))
        #批量插入数据,
        models.Article2Tag.objects.bulk_create(article_obj_list)
        return HttpResponseRedirect('/app01/backend/')


    return render(request,'app01/add_article.html',locals())

#产生5个随机字符，A-Z，a-z,0-9
def random_code(n=5):
    upper = chr(random.randint(65,90))
    lower = chr(random.randint(97,122))
    num = str(random.randint(0,9))
    code =''
    for i in range(n):
        code+=random.choice([upper,lower,num])
    return code


#获取一级目录下的文件名，
def get_filename(path):

    lis=os.listdir(path)#拿到目录下所有的文件名或目录名
    file_lis=[]
    for file in lis:
        file_path = os.path.join(path,file)
        if os.path.isfile(file_path):
            file_lis.append(file)
    return file_lis
from BBS14 import settings
#处理富文本框上传的图片的函数，将图片保存到media文件夹中保存
def upload_img(request):
    '''
    //成功时
{
        "error" : 0,
        "url" : "http://www.example.com/path/to/file.ext"//返回图片的完整路径
}
//失败时
{
        "error" : 1,
        "message" : "错误信息"
}

    :param request:
    :return:
    '''
    if request.method=='POST':
        back_dic ={"error" : 0,}
        file = request.FILES.get('imgFile')
        img_name=file.name
        #需要手动将文件保存到media文件夹中，
        #如何拼接文件路径，使用下面的方式，就是在业务上线也不会错
        dir_path=os.path.join(settings.BASE_DIR,'media','article_img')
        #先判断文件夹是否存在，不存在就创建
        if not os.path.isdir(dir_path):
            os.mkdir(dir_path)#不是目录就说明不存在，直接创建改目录
        try :
            file_lis = get_filename(dir_path)
            for name in file_lis:#如果用户上传的图片跟要保存的图片重命，就直接改名。
                if img_name==name:
                    pre,nex = img_name.split('.')
                    code = random_code()
                    img_name=str(pre)+str(code)+'.'+str(nex)
                    break
            # 拼接图片的完整路径，
            img_path = os.path.join(dir_path, img_name)
            with open(img_path,'wb') as fp:
                for line in file:
                    fp.write(line)
            back_dic['url']='/media/article_img/%s'% img_name
            return JsonResponse(back_dic)
        except Exception as  e:
            print(' in upload_img:',e)
            back_dic['error']=1
            back_dic['msg']='上传失败'
            return JsonResponse(back_dic)

#展示用户的班级信息
@login_required
def MyClass(request):
    theClass = models.UserInfo.objects.filter(stu_class=request.user.stu_class,is_active=True)
    #把自己排除掉，不显示
    theClass=theClass.exclude(id=request.user.id)
    # 拿到登录的用户所有的文章，显示出来
    # 拿到当前的页面
    cur_page = request.GET.get('page', 1)
    c_page = theClass
    page_html = ''
    if theClass.count() > 5:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=theClass.count(), per_page_count=5, max_pager_num=5)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = theClass[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
    return render(request,'app01/myclass.html',locals())

#修改头像
@login_required
def chang_avatar(request):
    url = request.GET.get('url')
    dic = {'msg': '', 'code': 1000, 'url':url}
    if request.is_ajax():
        if request.method=='POST':
            file = request.FILES.get('file')
            #修改用户头像时，使用对象的方法，三步走
            try :
                #头像保存在用户表中，拿到用户表对象
                file_obj = request.user
                #修改保存用户头像的字段avatar
                file_obj.avatar=file
                #一定不要忘记save()
                file_obj.save()
                dic['msg']='上传成功'
            except Exception as e:
                dic['msg']='上传失败'
                dic['code']=2000
            return JsonResponse(dic)
    return render(request,'app01/change_avatar.html',locals())

@login_required
def change_datas(request):
    if request.is_ajax():
        dic={'msg':'','code':1000,'url':'/app01/backend/'}
        if request.method=='POST':
            phone = request.POST.get('phone')
            title = request.POST.get('title')
            file = request.FILES.get('file')
            email = request.POST.get('email')
            stu_class=request.POST.get('stu_class','')
            try:
                if  file:
                    #修改图片使用三步走方式来修改
                    file_obj = request.user
                    file_obj.avatar=file
                    file_obj.save()

                #修改手机号码
                try:
                    models.UserInfo.objects.filter(username=request.user.username).update(phone=phone,email=email,stu_class=stu_class)

                    #修改个人站点签名
                    if title:
                        models.Blog.objects.filter(site_name=request.user.username).update(site_title=title)
                except:
                    pass
                dic['msg']='成功'
                return JsonResponse(dic)
            except Exception as  e:
                print('in change_datas:',e)
                dic['code']=2000
                dic['msg']='修改失败'
                return JsonResponse(dic)
    return render(request,'app01/editor_article.html',locals())

@login_required
def editor_article(request):
    #获取站点的所有分类用于显示，供用户选择
    category_obj = models.Category.objects.filter(blog__userinfo=request.user)
    #获取站点的所有标签用于显示，供用户选择
    tag_obj = models.Tag.objects.filter(blog__userinfo=request.user)
    #获取要修改的文章的id值，找到要操作哪篇文章
    article_id = request.GET.get('article_id')
    #获取文章对象
    article = models.Article.objects.filter(id=article_id).first()
    #获取当前文章的标签对象，设置位默认选择的标签
    obj_tag= models.Article2Tag.objects.filter(article_id=article_id)
    tag_lis=[]
    for tag in obj_tag:
        tag_lis.append(tag.tag_id)
    #获取当前文章的分类
    category_name =  models.Blog.objects.filter(article__id=article_id,site_name=request.user.username).values('article__category__name').first()
    if request.method=='POST':
        dic={'msg':'','code':1000}
        content=request.POST.get('content')
        title = request.POST.get('title')
        tag_id_list = request.POST.getlist('tag')
        category_id=request.POST.get('category')
        article_id=request.POST.get('article_id')
        soup = BeautifulSoup(content,'html.parser')
        tags = soup.find_all()
        for tag in tags:#删除所有的script标签
            if tag.name=='script':
                tag.decompose()
        desc = soup.text[0:150]
        #将数据写到数据库中。
        #更新文章
        try:
            models.Article.objects.filter(id=article_id).update(title=title,content=content,desc=desc,category_id=category_id)
            dic['msg']='修改成功'
            return HttpResponse('修改成功')
        except Exception as e:
          return HttpResponse('修改失败')
        #写到第三张表中，文章与标签
        #标签不改了。要更新多个标签，现在的我好像还做不到。
        #文件的删除的逻辑


    return render(request, 'app01/editor_article.html',locals())

@login_required
def upload_file(request):
    if request.is_ajax():
        print(12345)
        if request.method=='POST':
            dic={'code':1000,'url':"",'msg0':'','msg1':'','msg2':'','msg3':''}
            file_obj = request.FILES.get('file')
            name = request.POST.get('filename')
            filedesc = request.POST.get('desc')
            share = request.POST.get('share',1)
            share=int(share)#后端传进来的是0或1字符串,改成int类型.
            che = request.POST.get('che')
            if not name:
                dic['msg2']='文件名不能为空.'
                dic['code']=2000
            if not filedesc:
                dic['code']=2000
                dic['msg3']='描述不能为空'
            if not file_obj:
                dic['code']=2000
                dic['msg1']='未选择文件.'

            if dic['code']==1000:
                #说明用户该输入的都输入了
                try :
                    filename = file_obj.name#用户上传的文件的真正名字,下载时需要用到
                    models.UserFile.objects.create(userinfo=request.user,desc=filedesc,name=name,share=share,file=file_obj,filename=filename)
                    dic['url']='/app01/backend/'
                    dic['msg0']='文件上传成功'
                    return JsonResponse(dic)
                except Exception as e:
                    print('in upload_file: ',e)
                    dic['code']=3000
                    dic['msg0']='文件上传失败'
                    return JsonResponse(dic)
            else:
               return JsonResponse(dic)
@login_required
def operate_file(request):
    return render(request,'app01/operate_file.html')

from django.http import FileResponse
@login_required
def download_file(request):
    name = request.GET.get('name')
    file_id = request.GET.get('file_id')
    file_user = models.UserInfo.objects.filter(userfile__id=file_id).values('username').first()['username']
    #如果下载文件的人不能文件上传者，则下载数加1
    if file_user!=request.user.username:
        models.UserFile.objects.filter(pk=file_id).update(number=F('number')+1)
    if name:
        #拼接文件路径
        filepath = os.path.join('F:/installsotf/python/BBS14/media/user_file',name)
        file = open(filepath,'rb')
        response = FileResponse(file)  # 生成文件对象
        response['Content-Type']='application/octet-stream'
        name=name#没有压缩的下载文件

        response['Content-Disposition']='attachment;filename ="%s"'%(name.encode('utf-8').decode('ISO-8859-1'))
        return response

from django.utils.safestring import mark_safe
#被处理后的标签,在前端可以被执行
@login_required
def preview_file(request):
    flag=False
    file_id = request.GET.get('file_id')
    #拿到文件对象
    file = models.UserFile.objects.filter(pk=file_id,is_active=1).first()
    #拿到文件内容,显示出来.
    filepath = os.path.join('F:/installsotf/python/BBS14/media/user_file', file.filename)
    backe_url=request.GET.get('url')
    try:
        with open(filepath,'r') as fp:
            file_content = fp.read()
        flag=True
    except Exception as e:
        pass
    try:
        with open(filepath,'r',encoding='utf-8')as f:
            file_content=fp.read()
        flag=True
    except Exception as e:
        pass
    if not flag: #文件不能预览时
        html = '''
         <h3>很抱歉,该文件暂不支持在线预览.</h3>
          <p>如有其他问题,可以联系 <span class="glyphicon glyphicon-envelope"></span> xxxx@qq.com或联系 <span class="glyphicon glyphicon-phone-alt"></span> 132xxxx3466</p>
           <h5><span style="color: #337ab7">您可以先下载到本地</span></h5>
        '''
        file_content=mark_safe(html)
    #文件收藏数
    file_count = models.User2File.objects.filter(file_id=file_id).count()
    #用户收藏的ajax请求
    col_obj = models.User2File.objects.filter(user=request.user, file_id=file_id).first()
    if col_obj:  # 有东西就说明用户收藏了该文件
        col_file = 'yes'
        img = '/static/img/active.png/'
    else:
        col_file = 'no'
        img = '/static/img/noactive.png/'
    if request.is_ajax():
        if request.method=='POST':
            operate = request.POST.get('operate')
            files_id = request.POST.get('file_id')
            operate=json.loads(operate)
            obj = models.User2File.objects.filter(user=request.user,file_id=files_id)
            if obj:#代表用户已经收藏了该文件
                if not operate:#用户要取消收藏：
                    obj.delete()
            else:#用户未收藏该文件
                if operate: #用户想收藏该文件
                    models.User2File.objects.create(user=request.user, file_id=files_id)
            return JsonResponse({'msg':'okok'})
    return render(request,'app01/preview_file.html',locals())
@login_required
def article_cellation(request):
    if request.is_ajax():
        if request.method == 'POST':
            article_id = request.POST.get('article_id')
            dic = {'msg': '取消收藏成功', 'code': 100}
            print(article_id,956)
            if article_id:
               obj= models.User2Article.objects.filter(user_id=request.user.pk, article_id=article_id).delete()

            else:
                dic['msg'] = '请求方式出错了'
                dic['code'] = 103
            return JsonResponse(dic)
    '''收藏文章的展示'''
    col_article = models.User2Article.objects.filter(user=request.user)
    article_page_html = ''
    if col_article.count() >= 3:
        # 文件的分页
        article_page = request.GET.get('page1', 1)
        file_pagenate = paginator1.Pagination(base_url=request.path_info, current_page=article_page,
                                              total_count=col_article.count(), per_page_count=3, max_pager_num=3)
        article_page_html = file_pagenate.page_html()
        col_article = col_article[file_pagenate.start:file_pagenate.end]

    return render(request,'app01/article_cellation.html',locals())
@login_required
def file_cellation(request):
    #移除收藏
    if request.is_ajax():
        if request.method == 'POST':
            file_id = request.POST.get('file_id')
            dic = {'msg': '取消收藏成功', 'code': 100}
            try:
               obj= models.User2File.objects.filter(user_id=request.user.pk,file_id=file_id)
               if obj:
                   obj.delete()
               else:
                   dic['msg']='请求方式出错'
                   dic['code']=103
            except:
                dic['msg'] = '请求方式出错了'
                dic['code'] = 103
            return JsonResponse(dic)
    username = request.user.username
    #收藏的文件展示
    col_file = models.User2File.objects.filter(user=request.user)
    article_page_html = ''
    if col_file.count() >= 3:
        # 文件的分页
        article_page = request.GET.get('page1', 1)
        file_pagenate = paginator1.Pagination(base_url=request.path_info, current_page=article_page,
                                              total_count=col_file.count(), per_page_count=3, max_pager_num=4)
        article_page_html = file_pagenate.page_html()
        col_file = col_file[file_pagenate.start:file_pagenate.end]

    return render(request,'app01/file_cellation.html',locals())
from Utils import email as MyEmail
#找回密码
def find_password(request):
    if request.is_ajax():
        if 'op' in request.POST :
            dic={'code':200}
            username = request.POST.get('username')
            email = request.POST.get('email')#该邮箱接收验证码
            print(username,email,895)
            obj = models.UserInfo.objects.filter(username=username,email=email)
            if obj:#说明用户和邮箱都正确，给用户绑定的邮箱发送验证码。
                code = random_code(6)
                print(code,899)
                email_obj = MyEmail.Send_mail(sender='13510391274@163.com',passward='IMJBAXPFAUJSXSUZ',receivers=email)
                name='五邑博客园@'
                text = f'您的验证码是:{code}'
                head = '请确认是本人操作，不要将验证码提供给其他人。验证码30分钟内有效。'
                email_obj.send(Name=name,ShowText=text,Header_show=head)
                #将验证码保存到session中，到时候直接取再对比,使用用户名作为key
                request.session[username]=code
                return JsonResponse(dic)
            else:
                dic['code']=500
                return JsonResponse(dic)
        elif 'submit' in request.POST:
            dic={'code':200}
            username = request.POST.get('username')
            email = request.POST.get('email')
            code=request.POST.get('code')
            obj = models.UserInfo.objects.filter(username=username,email=email).first()
            if obj:
                #用户写的验证码跟保存在session中的一样就可以了。
                if code.upper()==request.session.get(username).upper():
                    dic['key1']='data-toggle'
                    dic['val1']='modal'
                    dic['key2']='data-target'
                    dic['val2']='#myModel'
                    dic['class']='"btn btn-danger btn-sm"'
                    return JsonResponse(dic)
                else:
                    return JsonResponse({'code':404,'msg':'验证码错误'})
            else:
                return JsonResponse({'code':500,'msg':'用户或邮箱错误'})
        elif 'reset' in request.POST:
            new_pwd = request.POST.get('new_pwd')
            confirm_pwd = request.POST.get('config_pwd')
            username = request.POST.get('username')
            dic={'code':200,'msg':'修改成功，请去登录'}
            code = request.session.get(username,None)
            if code:
                if new_pwd==confirm_pwd:
                    # 修改密码
                    try:
                        user_obj=models.UserInfo.objects.filter(username=username).first()
                        user_obj.set_password(new_pwd)
                        # 保存结果到数据库中
                        user_obj.save()
                        return JsonResponse(dic)
                    except:
                        dic['code']=500
                        dic['msg']='修改密码失败。'
                        return JsonResponse(dic)
                else:
                    dic['code']=404
                    dic['msg']='两次密码不一致'
                    return JsonResponse(dic)
                    # 跳转到登录界面重新登录
            else:
                dic['code']=403
                dic['msg']='用户名错误，需要找回密码的不是该用户'
                return JsonResponse(dic)
    return render(request,'app01/find_password.html')
#搜索功能的实现
from django.db.models import Q
def search(request):
    # 文件和文章推荐，
    good_article = models.Article.objects.all().order_by('-comment_num')[0:5]
    good_file = models.UserFile.objects.all().order_by('-number')[0:5]
    # #优秀用户
    # good_user =models.Article.objects.values('blog').annotate(article_num=Count('blog')).order_by('-article_num')[:5]
    # 最新文章
    new_article = models.Article.objects.order_by('-create_time')[:5]
    # 最新文件
    new_files = models.UserFile.objects.order_by('-create_time')[:5]
    if request.method=='POST':
        content = request.POST.get('content')
        choice = request.POST.get('choice')
        url=request.POST.get('url')
        #拿到要返回的html页面，主要是给管理员的搜索框设计的。
        html = request.POST.get('html')
        if choice=='100':#用户
            if content:
                obj=models.UserInfo.objects.filter(username__icontains=content)
                role='用户'
        elif choice=='200':
            if content:
                obj = models.Article.objects.filter(Q(title__icontains=content)|Q(desc__icontains=content))
                role = '文章'
        elif choice=='300':
            if content:
                obj = models.UserFile.objects.filter(Q(name__icontains=content)|Q(desc__icontains=content))
                role = '文件'
        elif choice=='10':#班级查
            if content:
                obj =models.UserInfo.objects.filter(stu_class__contains=content)
                role = '班级'
        elif choice=='11':
            obj = models.Resource.objects.filter(Q(name__contains=content)|Q(descn__contains=content))
            role='资源'
        else:
            role='没有'
        if not html:
            #用户的搜索框
            return  render(request,'app01/search_result.html',locals())
        else:
            #管理员的搜索框
            return  render(request,'app01/admin/home_search.html',locals())
    return render(request,'app01/search_result.html',locals())


#站点文件的显示
@login_required
def site_file(request,username):
    url = request.GET.get('back_url','/app01/home/')
    back_url=url
    blog = models.Blog.objects.filter(userinfo__username=username).first()
    files = models.UserFile.objects.filter(userinfo__username=username,is_active=1,share=1)
    count =files.count()
    #分页数据的显示
    # 拿到登录的用户所有的文章，显示出来
    article_obj = files
    # 拿到当前的页面
    cur_page = request.GET.get('page', 1)
    c_page = article_obj
    page_html = ''
    if article_obj.count() > 2:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=article_obj.count(), per_page_count=3, max_pager_num=4)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据

    return render(request,'app01/site_file.html',locals())

#处理关注的逻辑
@login_required
def focu_user(request):
    if request.is_ajax():
        if request.method=='GET':
            dic={'code':200,'msg':'关注成功'}
            my_name = request.GET.get('my_name')
            focu_name = request.GET.get('focu_name')
            my_obj = models.UserInfo.objects.filter(username=my_name).first()
            focu_obj = models.UserInfo.objects.filter(username=focu_name).first()
            if my_name==focu_name:
                dic['code']=300
                dic['msg']='不能关注自己。'
            else:
                obj =models.User2User.objects.filter(fans_user=my_obj,star_user=focu_obj)
                if obj:
                    dic['code']=400
                    dic['msg']='已经关注过了。'
                else:
                    models.User2User.objects.create(fans_user=my_obj,star_user=focu_obj)
            return JsonResponse(dic)
#个人管理中显示我关注的用户
@login_required
def my_focu(request):
    fcou_obj = models.User2User.objects.filter(fans_user=request.user)
    back_url = request.GET.get('url','/app01/home/')
    return render(request,'app01/show_my_focus.html',locals())
#管理员的管理界面 #登录且是管理员账户才能进入 ，学生账户展示
@login_required
def admin_home(request):
    # if request.user.username.startswith('admin512'):
    if request.user.username[:5]=='admin':
        #学生以312开头，3120001
        students = models.UserInfo.objects.filter(is_active=1,username__startswith='31200').order_by('stu_class') #按班级排序
        # 拿到登录的用户所有的文章，显示出来
        article_obj = students
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj
        page_html = ''
        if article_obj.count() > 3:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                            total_count=article_obj.count(), per_page_count=8, max_pager_num=4)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据

        if request.is_ajax():
            if request.method == 'POST':
                if 'delete' in request.POST:
                    del_id = request.POST.get('del_id')
                    op = request.POST.get('op')
                    print(del_id, 1090)
                    dic = {'code': 100, 'msg': '删除成功'}
                    if op:
                        models.UserInfo.objects.filter(id=del_id).update(is_active=0)
                        return JsonResponse(dic)
                    else:
                        dic['code'] = 200
                        dic['msg'] = '删除失败'
                        return JsonResponse(dic)

                elif 'limit' in request.POST:#禁言和解除禁言
                    limit_id =request.POST.get('limit_id')
                    op = request.POST.get('op')#数字1或0
                    op=int(op)
                    dic2={'code':100,'op':op}
                    print(op,1097)
                    try:
                        models.UserInfo.objects.filter(id=limit_id).update(limit=op)
                    except:
                        dic2['code']=200
                        dic2['msg']='操作失败'
                    return JsonResponse(dic2)
        #get请求返回的页面
        return render(request, 'app01/admin/home.html', locals())
    else:
        return render(request,'app01/admin/403.html')
#登录且是管理员账户才能进入，老师账户展示
@login_required
def admin_teacher(request):
    if request.user.username[:5]=='admin':
        # if request.user.username.startswith('admin512'):
        #     pass
        # else:return render(request,'app01/admin/403.html')
        teacher = models.UserInfo.objects.filter(is_active=1,username__startswith='51200')#username__startswith='512'
        article_obj = teacher
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj
        page_html = ''
        if article_obj.count() > 3:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                            total_count=article_obj.count(), per_page_count=8, max_pager_num=4)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
        if request.is_ajax():
            if request.method == 'POST':
                del_id = request.POST.get('del_id')
                op = request.POST.get('op')
                # print(del_id, 1090)
                dic = {'code': 100, 'msg': '删除成功'}
                if op:
                    models.UserInfo.objects.filter(id=del_id).update(is_active=0)

                else:
                    dic['code'] = 200
                    dic['msg'] = '删除失败'
                return JsonResponse(dic)

        return render(request,'app01/admin/home_teacher.html',locals())
    else:
        return render(request,'app01/admin/403.html')
#登录且是管理员账户才能进入,文章展示
@login_required
def admin_article(request):
    if request.user.username[:5]=='admin':
        articles = models.Article.objects.filter(is_active=1)
        article_obj = articles
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj
        page_html = ''
        if article_obj.count() > 3:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                            total_count=article_obj.count(), per_page_count=8, max_pager_num=4)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
        if request.is_ajax():
            if request.method=='POST':
                del_id=request.POST.get('del_id')
                op = request.POST.get('op')
                # print(del_id,1090)
                dic={'code':100,'msg':'删除成功'}
                if op:
                    models.Article.objects.filter(id=del_id).update(is_active=0)
                    return JsonResponse(dic)
                else:
                    dic['code']=200
                    dic['msg']='删除失败'
        return render(request,'app01/admin/home_article.html',locals())
    else:
        return render(request,'app01/admin/403.html')
#登录且是管理员账户才能进入，文件展示
@login_required
def admin_file(request):
    if request.user.username[:5]=='admin':
        files = models.UserFile.objects.filter(is_active=1,share=1)
        article_obj = files
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj
        page_html = ''
        if article_obj.count() > 3:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                            total_count=article_obj.count(), per_page_count=8, max_pager_num=4)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
        if request.is_ajax():
            if request.method=='POST':
                del_id=request.POST.get('del_id')
                op = request.POST.get('op')
                # print(del_id,1090)
                dic={'code':100,'msg':'删除成功'}
                if op:
                    models.UserFile.objects.filter(id=del_id).update(is_active=0)
                    return JsonResponse(dic)
                else:
                    dic['code']=200
                    dic['msg']='删除失败'
        return render(request,'app01/admin/home_file.html',locals())
    else:
        return render(request,'app01/admin/403.html')
#管理员上传文件
@login_required
def admin_upload(request):
    if request.user.username[:5]=='admin':
        if request.is_ajax():
            if request.method=='POST':
                name = request.POST.get('name')
                file = request.FILES.get('file')
                dic={'code':100,'msg':'上传成功'}
                filename = file.name
                # print(filename,1164)
                file_type= filename.split('.')[-1]
                # print(file_type)
                if file_type=='txt':
                    if file :
                        models.AdminFile.objects.create(name=name,filename=file.name,file=file,userinfo=request.user)

                    else:
                        dic['code']=200
                        dic['msg']='上传失败'
                else:
                    dic['msg']='无法接收，请上传txt格式文件！！'
                    dic['code']=500
                return JsonResponse(dic)
        return render(request,'app01/admin/home_upload.html')
    else:
        return render(request,'app01/admin/403.html')


# 展示管理员上传的文件
@login_required
def admin_upload_files(request):
    if request.user.username[:5]=='admin':
        files = models.AdminFile.objects.filter(is_active=1)
        article_obj = files
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj
        page_html = ''
        if article_obj.count() > 3:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                            total_count=article_obj.count(), per_page_count=8, max_pager_num=4)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
        if request.is_ajax():
            if request.method == 'POST':
                del_id = request.POST.get('del_id')
                op = request.POST.get('op')
                op = json.loads(op) #反序列化成pyhton的数据格式
                print(op,1259,type(op))
                dic = {'code': 100, 'msg': '删除成功'}
                if op:
                    models.AdminFile.objects.filter(id=del_id).update(is_active=0)

                else:
                    dic['code'] = 200
                    dic['msg'] = '删除失败'
                return JsonResponse(dic)
            elif request.method =='GET':
                pass
        return render(request, 'app01/admin/home_admin_file.html', locals())
    else:
        return render(request,'app01/admin/403.html')

#处理格式化文件，批量导入用户信息，并创建用户
@login_required
def admin_add_users(request):
    #在home_admin_file.html使用ajax请求发送到这里来的。
    if request.user.username[:5]=='admin':
        filename=request.GET.get('filename')
        status = request.GET.get('status')
        id=request.GET.get('id')
        print(type(status),status)
        user_obj = []
        success_user=[]
        error_user=[]
        with open(r'media\admin_file\%s'%filename,'r',encoding='utf-8')as p:
            if status=='False':#该文件未导入过
                for line in p:
                    tup = tuple(line.split('|')) #(学号,密码，邮箱,手机号，班级)
                    try:
                        if tup[0][:3]=='312':
                            the_class=tup[4] #这里可能报错的。
                        elif tup[0][:3]=='512':
                            the_class='' #老师不给设置班级
                        else:
                            error_user.append(tup)
                            continue #如果创建的用户不是本校的学生或老师，直接跳过，不创建。
                        #没有这个用户才创建。
                        if not models.UserInfo.objects.filter(username=tup[0]):
                            models.UserInfo.objects.create_user(username=tup[0],password=tup[1],email=tup[2],phone=tup[3],stu_class=the_class)
                            success_user.append(tup)
                        else:
                            error_user.append(tup)
                        if not models.Blog.objects.filter(site_name=tup[0]):
                            #给批量注册的用户创建个人站点
                            user_blog=models.Blog.objects.create(site_name=tup[0],site_theme=tup[0]+'.css')
                            # print(user_blog.site_title,1236)
                            #将用户与站点关联起来
                            models.UserInfo.objects.filter(username=tup[0]).update(blog=user_blog)
                    except:
                        error_user.append(tup[0]) #将出错的用户都加到这里来。
                        pass
                models.AdminFile.objects.filter(id=id).update(status=1)
            else:
                msg='文件已经导入过了,不能再导入。'
        return render(request, 'app01/admin/add_user.html', locals())
    else:
        return render(request,'app01/admin/403.html')
#
#用来删除数据的
def delete(request):
    if request.user.username.startswith('admin'):
        models.UserInfo.objects.filter(stu_class='200739').delete()
        return HttpResponse('okokok')
    else:
        return render(request,'app01/admin/403.html')
#设置
def set(request):
    models.UserInfo.objects.filter(Q(username__startswith='admin')|Q(username__startswith='512')).update(stu_class='')
    return HttpResponse('okokok')
#修改管理员信息
@login_required
def change_admin(request):
    if request.user.username.startswith('admin'):
        if request.is_ajax():
            if request.method=='POST':
                phone = request.POST.get('phone')
                email = request.POST.get('email')
                file = request.FILES.get('file')
                # print(phone,1288)
                dic={'code':1000,'msg':"修改成功",'url':reverse('app01_change_admin')}
                try:
                    if phone:
                        models.UserInfo.objects.filter(username=request.user.username).update( phone=phone)
                    if email:
                        models.UserInfo.objects.filter(username=request.user.username).update(email=email)
                    if file:
                        #修改图片要这样修改
                        img_obj = request.user
                        img_obj.avatar=file
                        img_obj.save()
                except:
                    dic['code']=2000
                    dic['msg']='修改失败'
                return JsonResponse(dic)
        return render(request,'app01/admin/home_admin_editor.html',locals())
    else:
        return render(request,'app01/admin/403.html')
#超级用户创建普通管理员
@login_required
def add_admin(request):
    if request.user.username.startswith('admin'):
        if request.is_ajax():
            if request.method=='POST':
                dic={'code':100,'msg':'创建管理员成功'}
                print(1311)
                if request.user.username=='admin':
                    print(1313)
                    username = request.POST.get('username')
                    email = request.POST.get('email')
                    phone = request.POST.get('phone')
                    pwd =request.POST.get('pwd')
                    pwd_agan = request.POST.get('pwd_agan')
                    if username[:8]=='admin512':
                        if pwd==pwd_agan:
                            obj = models.UserInfo.objects.filter(username=username)
                            if  not obj:
                                try:
                                    models.UserInfo.objects.create_user(username=username,password=pwd,email=email,phone=phone)
                                    dic['url']='/app01/admin/'
                                except:
                                    dic['code']=500
                                    dic['msg']='创建失败'
                            else:
                                dic['code']=600
                                dic['msg']='该用户已经存在了。'
                        else:
                            dic['code']=200
                            dic['msg']='密码不一致'
                    else:
                        dic['code']=300
                        dic['msg']='非法的用户名，使用admin512xxx格式。'
                else:
                    dic['code']=403
                    dic['msg']='您没有权限创建管理员账户。'
                return JsonResponse(dic)
        return render(request,'app01/admin/add_admin.html')
    else:
        return render(request,'app01/admin/403.html')
#显示所有普通管理员
@login_required
def show_admin(request):
    if request.user.username.startswith('admin'):
        amdin = models.UserInfo.objects.filter(username__startswith='admin512')
        article_obj = amdin
        # 拿到当前的页面
        cur_page = request.GET.get('page', 1)
        c_page = article_obj
        page_html = ''
        if article_obj.count() > 3:
            # 调用分页器
            pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,total_count=article_obj.count(), per_page_count=8, max_pager_num=4)
            # 分页器的前端代码
            page_html = pagenate.page_html()
            c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据

        return render(request,'app01/admin/show_admin.html',locals())
    else:
        return render(request,'app01/admin/403.html')

#添加单个用户
def admin_add_user(request):
    if request.is_ajax():
        if request.method=='POST':
            user=request.POST.get('user')
            email = request.POST.get('email')
            phone = request.POST.get('phone')
            stu_class =request.POST.get('class')
            password = request.POST.get('password')
            user_title= user[:3]
            dic={'code':100,'msg':'成功'}
            if user_title=='512' or user_title=='312':
                obj= models.UserInfo.objects.filter(username=user)
                if not obj:
                    models.UserInfo.objects.create_user(username=user,password=password,email=email,phone=phone,stu_class=stu_class)
                else:
                    dic['code']=400
                    dic['msg']='用户已经注册过了，不能再注册。'
            else:
                dic['code']=200
                dic['msg']='非本校学生和职工，不能注册。'
            return JsonResponse(dic)
    return render(request,'app01/admin/admin_add_user.html',locals())
#管理学生
def manage_student(request):
    article_obj = models.UserInfo.objects.filter(username__startswith='312')
    # 拿到当前的页面
    cur_page = request.GET.get('page', 1)
    c_page = article_obj
    page_html = ''
    if article_obj.count() > 3:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page, total_count=article_obj.count(), per_page_count=8, max_pager_num=8)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
    if request.is_ajax():
        if request.method=='POST':
            limit_id = request.POST.get('limit_id')
            op = request.POST.get('op')  # 数字1或0
            op = int(op)
            dic2 = {'code': 100, 'op': op}
            print(op, 1097)
            try:
                models.UserInfo.objects.filter(id=limit_id).update(limit=op)
            except:
                dic2['code'] = 200
                dic2['msg'] = '操作失败'
            return JsonResponse(dic2)
    return render(request,'app01/teacher/manage_stu.html',locals())
#私信功能
@login_required
def userWechat(request):
    if request.is_ajax():
        if request.method=='POST':
            content = request.POST.get('content')
            recv_id = request.POST.get('recv')
            dic={'msg':'','code':100}
            if content and recv_id:
                models.User2UserWechat.objects.create(send=request.user.id,recv=recv_id,content=content)
            else:
                dic['code']=404
                dic['code']='发送失败'
            return JsonResponse(dic)
        else:
            pass
    pk = request.GET.get('pk')
    user = models.UserInfo.objects.filter(id=pk).first()
    content = models.User2UserWechat.objects.filter(Q(send=request.user.pk,recv=pk)|Q(recv=request.user.pk,send=pk))
    #我接收的，且是当前私信的用户发送给的才是已读
    obj = models.User2UserWechat.objects.filter(recv=request.user.id,status=1,send=pk).update(status=2)
    return render(request,'app01/userwechat.html',locals())

#未读消息的查收
@login_required
def message(request):
    recv = models.User2UserWechat.objects.filter(recv=request.user.id,status=1)
    sends = recv.values('send').distinct()
    count = len(sends)
    if sends:
        send_lis=[ models.UserInfo.objects.filter(id=send_pk.get('send')).first() for send_pk in sends]
    return render(request,'app01/mymessage.html',locals())
#用户评论管理
@login_required
def admin_user_comment(request):
    article_obj =  models.Comment.objects.all()
    cur_page = request.GET.get('page', 1)
    c_page = article_obj
    page_html = ''
    if article_obj.count() > 5:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=article_obj.count(), per_page_count=5, max_pager_num=5)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
    if request.is_ajax():
        if request.method=='POST':
            op = request.POST.get('op')
            comt_id = request.POST.get('del_id')
            dic={'msg':'删除成功','code':100}
            if op:
                if comt_id:
                    comt = models.Comment.objects.filter(id=comt_id).first()
                    print(comt.content,1596)
                else:
                    dic['code']=200
                    dic['msg']='无此评论'
            else:
                dic['code']=200
                dic['msg']='请求错误'
            return JsonResponse(dic)
    return render(request, 'app01/admin/admin_user_comment.html', locals())
#用户资源管理
@login_required
def admin_source(request):
    article_obj = models.Resource.objects.filter(is_delete=False)
    cur_page = request.GET.get('page', 1)
    c_page = article_obj
    page_html = ''
    if article_obj.count() > 10:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=article_obj.count(), per_page_count=10, max_pager_num=10)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
    if request.is_ajax():
        if request.method=='POST':
            if 'source_id' in request.POST:
                source_id = request.POST.get('source_id')
                level = request.POST.get('level')
                dic={'msg':'修改成功','code':100}
                try:
                    level = int(level)
                    if level >0 and level<4:
                        models.Resource.objects.filter(pk=source_id).update(level=level)
                    else:
                        dic['msg']='资源等级只有，初级(3)、中级(2)、高级(1)'
                        dic['code']=102
                except:
                    dic['msg']='请求错误'
                    dic['code']=101
                return JsonResponse(dic)



            del_id =request.POST.get('del_id')
            op = request.POST.get('op')
            dic = {'msg':'删除成功','code':100}
            if op=='true' and op:
                models.Resource.objects.filter(pk=del_id).update(is_delete=True)
            else:
                dic['msg']='操作失败'
                dic['code']=200
            return JsonResponse(dic)
    return render(request,'app01/admin/admin_source.html',locals())
#web资源
@login_required
def web_sourse(request):
    soures = models.Categorys.objects.filter(userinfo=request.user)
    if request.is_ajax():
        if request.method=='POST':
            source_name = request.POST.get('source_name')
            source_desc = request.POST.get('source_desc')
            dic={
                'code':100,
                'msg':'创建成功'
            }
            if source_name and source_desc:
                source = models.Categorys.objects.filter(userinfo=request.user,name=source_name).first()
                if source:
                    dic['code']=300
                    dic['msg']='该分类名已经存在了。'
                else:
                    models.Categorys.objects.create(userinfo=request.user,name=source_name,descn=source_desc)
                    dic['msg']=f'创建“{source_name}”资源分类成功'
            elif not source_name:
                dic['code']=202
                dic['msg']='资源分类名不能为空'
            elif not source_desc:
                dic['code']=204
                dic['msg']='资源分类描述不能为空'
            return JsonResponse(dic)

    return render(request,'app01/web_sourse/web_sourse.html',locals())

#上传web资源
@login_required
def up_web_source(request):
    if request.is_ajax():
        if request.method=='POST':
            sou_name = request.POST.get('sou_name')
            sou_desc = request.POST.get('sou_desc')
            sou_img = request.FILES.get('sou_img')
            sou_code = request.FILES.get('sou_code')
            cate_id = request.POST.get('cate_id')
            dic={'msg':'创建资源成功','code':100}
            if sou_code and sou_img and sou_desc and sou_name:
                img_type = ['jpg', 'png', 'gif','GIF','JPG','PNG']
                filename = sou_code.name  # 获取上的文件的名字
                img = sou_img.name.split('.')[-1]
                code_file = sou_code.name.split('.')[-1]
                # 限制图片格式，也可以防止用户将文件上传到这里
                if img not in img_type:
                    dic['msg'] = '上传的图片格式必须：jpg,png,gif'
                    dic['code'] = 101
                    return JsonResponse(dic)
                elif code_file != 'txt':  # 限制用户上传的文件格式
                    dic['msg'] = '上传的文件格式必须是.txt '
                    dic['code'] = 101
                    return JsonResponse(dic)
                models.Resource.objects.create(name=sou_name,descn=sou_desc,image=sou_img,code=sou_code,categoryid_id=cate_id,uploader=request.user,filename=filename)

            else:
                dic['code'] = 101
                if not sou_name:
                    dic['msg']='没有资源名'
                if not sou_desc:
                    dic['msg']='没有资源描述'
                if not sou_img:
                    dic['msg']='没有上传资源效果图'
                if not sou_code:
                    dic['msg']='没有资源代码'
                if not  cate_id :
                    dic['msg']='没有选择分离'
            return JsonResponse(dic)
    cate = models.Categorys.objects.filter(userinfo=request.user)
    return render(request,'app01/web_sourse/up_web_source.html',locals())

#展示我的web资源
@login_required
def show_web_source(request):
    sources = models.Resource.objects.filter(uploader=request.user,is_delete=False)
    #分页
    article_obj =sources
    # 拿到当前的页面
    cur_page = request.GET.get('page', 1)
    c_page = article_obj
    page_html = ''
    if article_obj.count() >=6:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=article_obj.count(), per_page_count=6, max_pager_num=6)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = article_obj[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据


    username = request.GET.get('username')
    file_id = request.GET.get('pk')
    if file_id:
        sou = models.Resource.objects.filter(pk=file_id).first()
        code_file = sou.code
        name = code_file.name #拿到文件名
        filepath = os.path.join('F:/installsotf/python/BBS14/media/', name)
        filename = sou.filename#代码的文件上传时的名字

        if filepath:
            if username: #如果有用户，如果没有就不进行比较
                if username != request.user.username:
                    obj = models.Resource.objects.filter(pk=file_id)
                    obj.update(down_numbers=F('down_numbers') + 1)
                    num = obj.first().down_numbers
                    if obj.first().down_numbers > 10:
                        # 如果下载数超过10，就是中级资源
                        obj.update(level=2)
                    elif obj.first().down_numbers > 100:
                        # 如果下载数超过100，就是中级资源
                        obj.update(level=1)
            #下面是文件下载的功能代码
            file = open(filepath, 'rb')
            response = FileResponse(file)  # 生成文件对象
            response['Content-Type'] = 'application/octet-stream'
            name = filename.split('.')[0] + '.txt' #'.tar.gz'
            response['Content-Disposition'] = 'attachment;filename ="%s"' % (name.encode('utf-8').decode('ISO-8859-1'))
            #给下载数加1，但是如果是下载自己的源代码就不会加1
            return response
    if request.is_ajax():
        #删除资源的ajax请求
        if request.method=="POST":
            source_id = request.POST.get('del_id')
            op=request.POST.get('op')
            dic={'msg':'删除成功','code':100}
            op = json.loads(op)
            if op and source_id:
                models.Resource.objects.filter(pk=source_id).update(is_delete=True)
            else:
                dic['code']=101
                dic['msg']='操作失败'
            return JsonResponse(dic)

    return render(request,'app01/web_sourse/show_web_source.html',locals())
#展示所有的web资源库
@login_required
def web_home(request):
    sources = models.Resource.objects.filter(is_delete=False)
    # 拿到登录的用户所有的文章，显示出来
    # 拿到当前的页面
    cur_page = request.GET.get('page', 1)
    c_page = sources
    page_html = ''
    if sources.count() > 6:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=sources.count(), per_page_count=6, max_pager_num=6)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = sources[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
    return render(request, 'app01/web_sourse/index.html', locals())

#预览某个资源
@login_required
def source_detail(request,username,sou_pk):
    sou_pk = request.GET.get('pk')
    #给include使用的。
    back_url=request.GET.get('url')
    #给templatetags下my_tag.py下left_menu函数传递username
    username=username
    #用户签名需要传递blog
    blog = models.Blog.objects.filter(userinfo__username=username).first()
    if sou_pk:
        source = models.Resource.objects.filter(pk=sou_pk).first()
        code_file = source.code
        name = code_file.name
        filepath = os.path.join('F:/installsotf/python/BBS14/media/', name)
        try:
            with open(filepath,'r') as fp:
                files=fp.readlines()
        except:
            try:
                with open(filepath, 'r',encoding='utf-8')as fp:
                    files = fp.readlines()
            except:
                files=['源代码无法打开','请下载到本地阅读。']


        # 用户收藏的ajax请求
    col_obj = models.User2Source.objects.filter(user_id=request.user, source_id_id=sou_pk).first()
    # 有东西就说明用户收藏了该文件
    if col_obj:
        col_file = 'yes'
        img = '/static/img/active.png/'
    else:
        col_file = 'no'
        img = '/static/img/noactive.png/'
    #收藏和取消收藏的ajax请求
    if request.is_ajax():
        if request.method == 'POST':
            operate = request.POST.get('operate')
            files_id = request.POST.get('file_id')
            operate = json.loads(operate)
            obj = models.User2Source.objects.filter(user_id=request.user, source_id_id=files_id)
            if obj:  # 代表用户已经收藏了该文件
                if not operate:  # 用户要取消收藏：
                    obj.delete()
            else:  # 用户未收藏该文件
                if operate:  # 用户想收藏该文件
                    models.User2Source.objects.create(user_id=request.user, source_id_id=files_id)
            return JsonResponse({'msg': 'okok'})
    return render(request,'app01/web_sourse/detail_souce.html',locals())

#用户收藏资源的界面
@login_required
def source_collection(request):
    if request.is_ajax():
        if request.method == 'POST':
            source_id = request.POST.get('source_id')
            dic = {'msg': '取消收藏成功', 'code': 100}
            try:
               obj= models.User2Source.objects.filter(user_id=request.user,source_id_id=source_id)
               if obj:
                   obj.delete()
               else:
                   dic['msg']='请求方式出错'
                   dic['code']=103
            except:
                dic['msg'] = '请求方式出错了'
                dic['code'] = 103
            return JsonResponse(dic)
    sources = models.User2Source.objects.filter(user_id=request.user)
    cur_page = request.GET.get('page', 1)
    c_page = sources
    page_html = ''
    if sources.count() > 3:
        # 调用分页器
        pagenate = paginator.Pagination(base_url=request.path_info, current_page=cur_page,
                                        total_count=sources.count(), per_page_count=3, max_pager_num=3)
        # 分页器的前端代码
        page_html = pagenate.page_html()
        c_page = sources[pagenate.start:pagenate.end]  # 拿到当前页需要展示的所有数据
    return render(request,'app01/web_sourse/source_collection.html',locals())

